import logging
import sys

import util.common
import io.ioloop

import api
import channel
import comm_id
import config
import method
import peer

log = logging.getLogger('tx')

#------------------------------------------------------------------------------
class Tx:
    """Transport daemon. Manages and multiplexes the available
    communication methods for upper level layers"""

    def __init__(self):
        self.api_      = None
        self.methods_  = {}              # name -> method.Method
        self.channels_ = []
        self.peers_    = {}              # name -> peer.Peer
        self.config_   = config.Config()
        
    def add_method(self, m):
        """Register a communications method"""
        if m.name() in self.methods_:
            log.warn('method %s has already been registered' % m.name())
        self.methods_[m.name()] = m
        log.info('register method %s' % m)

    def get_method(self, n):
        return self.methods_[n]

    def get_peer(self, id):
        """Register an open communications channel for id."""
        if id not in self.peers_:
            self.peers_[id] = peer.Peer(id, self)
        return self.peers_[id]

    def get_peers(self):
        return self.peers_

    def get_channel_summary(self):
        """Returns a summary of the channels that are open"""
        ret = []
        for c in self.channels_:
            ret.append(c.summary())
        return ret

    def get_comm_by_id(self, c_id):
        assert isinstance(c_id, comm_id.CommId)
        assert c_id.peer_id != comm_id.CommId.ANY
        p = self.get_peer(c_id.peer_id)
        return p.get_comm_by_id(c_id)
        
    def config(self):
        """Setup all of the transport methods, channels"""
        for name in self.config_.transports.keys():
            m = method.parse_method(name, self.config_.transports[name], self)
            self.add_method(m)

        log.debug('--- API ---')
        log.debug('API is running on %s:%s' %
                  (self.config_.ap[0], self.config_.ap[1]))
        self.api_ = api.Api(self.config_.ap, self)
        assert self.api_ != None
        
        log.debug('--- METHODS ---')
        for i in self.methods_.keys():
            log.debug('    %s' % self.methods_[i])

    def neon_id(self):
        """Convenience function for accessing neon id"""
        return self.config_.id

    def api(self):
        assert self.api_ != None
        return self.api_

    def run(self):
        """Run the daemon until killed or CTRL-break"""
        for i in self.methods_.keys():
            self.methods_[i].start()
	log.info('tx started')
        io.ioloop.master_loop.set_exit_cb(self.quit)
        util.common.dtest('tx', 'running:1')
        io.ioloop.master_loop.run()

    def quit(self):
        """Terminate tx"""
        log.info('got command from client, exiting...')
        util.common.dtest('tx', 'running:0')
        sys.exit(0)

#------------------------------------------------------------------------------
if __name__ == '__main__':
    tx = Tx()
    tx.config()
    tx.run()
